package middleware

import (
	"encoding/json"
	"fmt"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/config"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/code"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/gin/log"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/jwt"
	"io"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
)

// JWTAuth 中间件，检查token
func JWTAuth(skipper ...SkipperFunc) gin.HandlerFunc {
	return func(c *gin.Context) {
		if len(skipper) > 0 && skipper[0](c) {
			c.Next()
			return
		}
		token := c.Request.Header.Get("token")
		if token == "" {
			c.JSON(400, gin.H{
				"code": code.Token_Error,
				"msg":  "请求未携带token，无权限访问",
			})
			c.Abort()
			return
		}
		log.Info("get token: ", token)
		// parseToken 解析token包含的信息
		claims, err := jwt.ParseTokenFromRedis(token)
		log.Info("get uid: ", claims.UserId)
		//中心化的管理端需要从缓存中取这个token是否过期
		//redisToken, err := redis.ImRedisDB.Exists("access_token_" + token).Result()
		if err != nil || claims.UserId == "" {
			c.JSON(400, gin.H{
				"code": code.Token_Error,
				"msg":  "token 失效",
			})
			c.Abort()
			return
		}
		log.Debug("set uid:", claims.UserId)
		// 继续交由下一个路由处理,并将解析出的信息传递下去
		c.Set("UID", claims.UserId)
	}
}

func OBSAuth(skipper ...SkipperFunc) gin.HandlerFunc {
	return func(c *gin.Context) {
		if len(skipper) > 0 && skipper[0](c) {
			c.Next()
			return
		}
		token := c.Request.Header.Get("token")
		if token == "" {
			c.JSON(400, gin.H{
				"code": code.Token_Error,
				"msg":  "请求未携带4A token,无权限访问",
			})
			c.Abort()
			return
		}

		claims, err := jwt.ParseTokenFromRedis(token)
		if err != nil || claims.UserId == "" {
			c.JSON(400, gin.H{
				"code": code.Token_Error,
				"msg":  "token 失效",
			})
			c.Abort()
			return
		}
		//[TODO] obs鉴权
		reqByte, _ := json.Marshal(map[string]interface{}{"clientId": config.C.OSB.ClientId, "password": config.C.OSB.Password})
		req, err := http.NewRequest("POST", config.C.OSB.UrlHost+"/ejdw/middleware/auth/token", strings.NewReader(string(reqByte)))
		if err != nil {
			c.JSON(400, gin.H{
				"code": code.BAD_LOGIN,
				"msg":  fmt.Sprintf("OSB Request错误, %v", err),
			})
			c.Abort()
			return
		}
		req.Header.Add("Content-Type", "application/json")
		client := &http.Client{}
		res, err := client.Do(req)
		if err != nil {
			c.JSON(400, gin.H{
				"code": code.BAD_LOGIN,
				"msg":  fmt.Sprintf("获取OSB Token失败, %v", err),
			})
			c.Abort()
			return
		}
		defer res.Body.Close()

		resBody, err := io.ReadAll(res.Body)
		if err != nil {
			c.JSON(400, gin.H{
				"code": code.BAD_LOGIN,
				"msg":  fmt.Sprintf("读取OSB Token数据失败, %v", err),
			})
			c.Abort()
			return
		}
		data := jwt.OBSAuthToken{}
		err = json.Unmarshal(resBody, &data)
		if err != nil {
			c.JSON(400, gin.H{
				"code": code.BAD_LOGIN,
				"msg":  fmt.Sprintf("提取OSB Token数据失败, %v, 返回数据: %s", err, string(resBody)),
			})
			c.Abort()
			return
		}

		if data.Code != 0 || data.Data.Token == "" {
			c.JSON(400, gin.H{
				"code": code.BAD_LOGIN,
				"msg":  fmt.Sprintf("获取OSB Token失败, %v, 返回数据: %s", err, string(resBody)),
			})
			c.Abort()
			return
		}
		c.Set("x-token", data.Data.Token)
		c.Request.Header.Set("x-token", data.Data.Token)
	}
}
